package com.eqxiu.ieditor.weixin.service;


import com.alibaba.dubbo.config.annotation.Service;
import com.eqxiu.ieditor.weixin.api.UnifiedOrderServiceApi;
import com.eqxiu.ieditor.weixin.common.properties.WxProperties;
import com.eqxiu.ieditor.weixin.dao.WeixinAppDao;
import com.eqxiu.ieditor.weixin.dto.UnifiedOrder;
import com.eqxiu.ieditor.weixin.model.WeixinApp;
import com.eqxiu.ieditor.weixin.model.WeixinAppExample;
import com.eqxiu.ieditor.weixin.util.HttpUtils;
import com.eqxiu.ieditor.weixin.util.NotFoundAppIdException;
import com.eqxiu.ieditor.weixin.util.WXPayConstants;
import com.eqxiu.ieditor.weixin.util.WXPayUtil;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

@Service
public class UnifiedOrderServiceApiImpl implements UnifiedOrderServiceApi {
	@Autowired
	private WeixinAppDao appDao;

	private Logger logger = LoggerFactory.getLogger(getClass().getName());
	static OkHttpClient client = HttpUtils.getUnsafeOkHttpClient();

	@Autowired
	private WxProperties properties;

	@Override
	public Map<String, Object> unifiedOrder(UnifiedOrder order) throws Exception {
		WeixinAppExample example = new WeixinAppExample();
		String appId = order.getAppId();
		example.createCriteria().andAppIdEqualTo(appId);
		List<WeixinApp> apps = appDao.selectByExample(example);
		if (apps == null || apps.size() == 0) {
			throw new NotFoundAppIdException("appid " + appId + " not found");
		}
		WeixinApp app = apps.get(0);

		Map<String, String> unifiedParam = new TreeMap<>();
		unifiedParam.put("appid", order.getAppId());
		unifiedParam.put("body", order.getBody());
		unifiedParam.put("mch_id", app.getMchId());
		unifiedParam.put("nonce_str", WXPayUtil.generateNonceStr());
		unifiedParam.put("spbill_create_ip", order.getSpbillCreateIp());
		unifiedParam.put("notify_url", properties.getStylishNotifyUrl());
		unifiedParam.put("trade_type", "JSAPI");
		unifiedParam.put("out_trade_no", order.getOutTradeNo());
		unifiedParam.put("total_fee", order.getTotalFee() + "");
		unifiedParam.put("openid", order.getOpenId());
		unifiedParam.put("sign_type", WXPayConstants.MD5);

		String sign = WXPayUtil.generateSignature(unifiedParam, app.getMchKey());

		unifiedParam.put("sign", sign);
		String reqBody = WXPayUtil.mapToXml(unifiedParam);
		Request request = new Request.Builder().url(properties.getUnifiedorderUrl())
				.post(RequestBody.create(MediaType.parse("text/xml; charset=UTF-8"), reqBody)).build();
		Map resultMap = new TreeMap<>();

		try (Response response = client.newCall(request).execute()) {
			String body = response.body().string();
			Map<String, String> element = WXPayUtil.xmlToMap(body);
			logger.info("weixin unifiedOrder return body {} ", element);
			String resultCode = element.get("return_code");
			String returnMsg = element.get("return_msg");
			if ("SUCCESS".equals(resultCode) && "OK".equals(returnMsg)) {
				String prepayId = element.get("prepay_id");
				resultMap.put("package", "prepay_id=" + prepayId);
				resultMap.put("timeStamp", System.currentTimeMillis() + "");
				resultMap.put("nonceStr", element.get("nonce_str"));
				resultMap.put("signType", WXPayConstants.MD5);
				resultMap.put("appId", appId);
				resultMap.put("paySign", WXPayUtil.generateSignature(resultMap, app.getMchKey()));
				return resultMap;
			}

		} catch (IOException e) {
			e.printStackTrace();
		}

		return resultMap;
	}

	@Override
	public String handleNotify(Map<String, String> map) throws Exception {
		WeixinAppExample example = new WeixinAppExample();
		String appId = map.get("appid");
		example.createCriteria().andAppIdEqualTo(appId);
		List<WeixinApp> apps = appDao.selectByExample(example);
		if (apps == null || apps.size() == 0) {
			return WXPayConstants.FAIL;

		}
		WeixinApp app = apps.get(0);

		boolean valid = WXPayUtil.isSignatureValid(map, app.getMchKey());
		if (!valid) {
			return "FAIL";
		}

		String resultCode = map.get("result_code");
		String returnCode = map.get("return_code");
		if (WXPayConstants.SUCCESS.equals(resultCode) && WXPayConstants.SUCCESS.equals(returnCode)) {
			return WXPayConstants.SUCCESS;
		}

		return WXPayConstants.FAIL;
	}

	@Override
	public String handleNotify(String notifyResult) throws Exception {
		Map<String, String> map = WXPayUtil.xmlToMap(notifyResult);
		
		WeixinAppExample example = new WeixinAppExample();
		String appId = map.get("appid");
		example.createCriteria().andAppIdEqualTo(appId);
		List<WeixinApp> apps = appDao.selectByExample(example);
		if (apps == null || apps.size() == 0) {
			return WXPayConstants.FAIL;

		}
		WeixinApp app = apps.get(0);

		boolean valid = WXPayUtil.isSignatureValid(map, app.getMchKey());
		if (!valid) {
			return "FAIL";
		}

		String resultCode = map.get("result_code");
		String returnCode = map.get("return_code");
		if (WXPayConstants.SUCCESS.equals(resultCode) && WXPayConstants.SUCCESS.equals(returnCode)) {
			return WXPayConstants.SUCCESS;
		}

		return WXPayConstants.FAIL;
	}

}
